/* app_rfft_example. */

#include "app.h"
#include "app_fft_data.h"


/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Code
 ******************************************************************************/

/* cmsis-dsp不推荐使用arm_rfft_f32(), 建议使用arm_rfft_fast_f32()取代. */
void app_arm_rfft_f32_example(void)
{
    arm_rfft_fast_instance_f32 arm_rfft_fast_instance;
    PRINTF("%s()\r\n", __func__);

    /* 准备输入数组. */
    app_init_rfft_input_f32(fft_input_f32, FFT_INPUT_NUM_512); /* 以实数的方式填充输入数组. */

    /* 准备一个rfft计算的实例对象, 将计算过程中使用的数据结构统一管理起来. */
    arm_rfft_fast_init_f32(&arm_rfft_fast_instance, FFT_INPUT_NUM_512);

    TimerCount_Start(); /* 开始计时. */

    /* 开始计算 */
    arm_rfft_fast_f32(&arm_rfft_fast_instance, fft_input_f32, fft_output_f32, 0);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    /* 打印计算结果. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512/2; i++) /* rfft只要一半的点数就能够表示足够的信息了. */
    {
        PRINTF("[%3d]: %f, %f\r\n", i, fft_output_f32[i*2], fft_output_f32[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}

void app_arm_rfft_q31_example(void)
{
    arm_rfft_instance_q31 arm_rfft_instance;
    PRINTF("%s()\r\n", __func__);

    /* 准备输入数组. */
    app_init_rfft_input_q31(fft_input_q31, FFT_INPUT_NUM_512); /* 以实数的方式填充输入数组. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++)
    {
          fft_input_q31[i] *= FFT_INPUT_NUM_512;
    }

    arm_rfft_init_q31(&arm_rfft_instance, FFT_INPUT_NUM_512, 0, 0);

    TimerCount_Start(); /* 开始计时. */

    arm_rfft_q31(&arm_rfft_instance, fft_input_q31, fft_output_q31);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    /* 打印计算结果. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++) /* rfft只要一半的点数就能够表示足够的信息了. */
    {
        PRINTF("[%3d]: %d, %d\r\n", i, fft_output_q31[i*2], fft_output_q31[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}

void app_arm_rfft_q15_example(void)
{
    arm_rfft_instance_q15 arm_rfft_instance;
    PRINTF("%s()\r\n", __func__);

    /* 准备输入数组. */
    app_init_rfft_input_q15(fft_input_q15, FFT_INPUT_NUM_512); /* 以实数的方式填充输入数组. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++)
    {
          fft_input_q15[i] *= FFT_INPUT_NUM_512;
    }

    arm_rfft_init_q15(&arm_rfft_instance, FFT_INPUT_NUM_512, 0, 0);

    TimerCount_Start(); /* 开始计时. */

    arm_rfft_q15(&arm_rfft_instance, fft_input_q15, fft_output_q15);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    /* 打印计算时间. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++) /* rfft只要一半的点数就能够表示足够的信息了. */
    {
        PRINTF("[%3d]: %d, %d\r\n", i, fft_output_q15[i*2], fft_output_q15[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}

/* 使用PowerQuad计算. */

#if 0 /* PQ_MatrixScale()硬件问题, 实际不能按照预期设计工作, 在当前硬件版本不提供pq的浮点数rfft实现. */
void app_pq_rfft_f32_example(void)
{
    pq_config_t pq_config;

    PRINTF("%s()\r\n", __func__);

    app_init_rfft_input_f32(fft_input_f32, FFT_INPUT_NUM_512); /* 实际使用了FFT_INPUT_NUM个内存空间. */

    TimerCount_Start(); /* 开始计时. */

    /* PowerQuad浮点数转定点数 */
    pq_config.inputAFormat = kPQ_Float;
    pq_config.inputAPrescale = 0;
    pq_config.outputFormat = kPQ_32Bit;
    pq_config.outputPrescale = 9;/* 乘以512. */
    pq_config.machineFormat = kPQ_Float;
    PQ_SetConfig(POWERQUAD, &pq_config);
    PQ_MatrixScale(POWERQUAD,
        POWERQUAD_MAKE_MATRIX_LEN(16, 16, 0), /* length = 256. */
        1.0f,
        (void *)fft_input_f32,
        (void *)fft_input_q31
        );
    PQ_WaitDone(POWERQUAD);
    PQ_MatrixScale(POWERQUAD,
        POWERQUAD_MAKE_MATRIX_LEN(16, 16, 0), /* length = 256. */
        1.0f,
        (void *)(fft_input_f32 + 256),
        (void *)(fft_input_q31 + 256)
        );
    PQ_WaitDone(POWERQUAD);

    /* 执行定点数FFT. */
    pq_config.inputAFormat = kPQ_32Bit;
    pq_config.inputAPrescale = 9; /* 抵消除以512的影响 */
    pq_config.outputFormat = kPQ_32Bit;
    pq_config.outputPrescale = 0;
    pq_config.tmpBase = (uint32_t *)0xE0000000; /* private ram. */
    pq_config.machineFormat = kPQ_32Bit;
    PQ_SetConfig(POWERQUAD, &pq_config);
    PQ_TransformRFFT(POWERQUAD,
        FFT_INPUT_NUM_512,
        fft_input_q31,
        fft_output_q31);
    PQ_WaitDone(POWERQUAD);

    /* PowerQuad定点数转浮点数. */
    pq_config.inputAFormat = kPQ_32Bit;
    pq_config.inputAPrescale = 0;
    pq_config.outputFormat = kPQ_Float;
    pq_config.outputPrescale = 0;
    pq_config.machineFormat = kPQ_Float;
    PQ_SetConfig(POWERQUAD, &pq_config);
    PQ_MatrixScale(POWERQUAD,
        POWERQUAD_MAKE_MATRIX_LEN(16, 16, 0), /* length = 256. */
        1.0f,
        (void *)fft_output_q31,
        (void *)fft_output_f32
        );
    PQ_WaitDone(POWERQUAD);
    PQ_MatrixScale(POWERQUAD,
        POWERQUAD_MAKE_MATRIX_LEN(16, 16, 0), /* length = 256. */
        1.0f,
        (void *)(fft_output_q31 + 256),
        (void *)(fft_output_f32 + 256)
        );
    PQ_WaitDone(POWERQUAD);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++)
    {
        PRINTF("[%3d]: %d, %d\r\n", i, fft_input_q31[i*2], fft_input_q31[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}
#endif

void app_pq_rfft_q31_example(void)
{
    pq_config_t pq_config;
    PRINTF("%s()\r\n", __func__);

    /* 准备输入数组. */
    app_init_rfft_input_q31(fft_input_q31, FFT_INPUT_NUM_512); /* 以实数的方式填充输入数组. */

    /* 配置PowerQuad的数据格式 */
    pq_config.inputAFormat = kPQ_32Bit;
    pq_config.inputAPrescale = 9; /* 输入乘以512, 抵消掉FFT引擎内部的除以512的操作. */
    pq_config.outputFormat = kPQ_32Bit;
    pq_config.outputPrescale = 0;
    pq_config.machineFormat = kPQ_32Bit;
    pq_config.tmpBase = (uint32_t *)0xE0000000; /* private ram. */
    PQ_SetConfig(POWERQUAD, &pq_config);

    TimerCount_Start(); /* 开始计时. */

    /* 使用PowerQuad的FFT引擎开始计算. */
    PQ_TransformRFFT(POWERQUAD,
        FFT_INPUT_NUM_512,
        fft_input_q31,
        fft_output_q31);
    PQ_WaitDone(POWERQUAD);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    /* 打印计算结果 */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++) /* rfft只要一半的点数就能够表示足够的信息了. */
    {
        PRINTF("[%3d]: %d, %d\r\n", i, fft_output_q31[i*2], fft_output_q31[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}

void app_pq_rfft_q15_example(void)
{
    pq_config_t pq_config;
    PRINTF("%s()\r\n", __func__);

    /* 准备输入数组. */
    app_init_rfft_input_q15(fft_input_q15, FFT_INPUT_NUM_512); /* 以实数的方式填充输入数组. */

    /* 配置PowerQuad的数据格式 */
    pq_config.inputAFormat = kPQ_16Bit; /* 16位数输入. */
    pq_config.inputAPrescale = 9; /* 输入乘以512, 抵消掉FFT引擎内部的除以512的操作. */
    pq_config.outputFormat = kPQ_16Bit; /* 32位数输出 */
    pq_config.outputPrescale = 0;
    pq_config.machineFormat = kPQ_32Bit;
    pq_config.tmpBase = (uint32_t *)0xE0000000; /* private ram. */
    PQ_SetConfig(POWERQUAD, &pq_config);

    TimerCount_Start(); /* 开始计时. */

    /* 使用PowerQuad的FFT引擎开始计算. */
    PQ_TransformRFFT(POWERQUAD,
        FFT_INPUT_NUM_512,
        fft_input_q15,
        fft_output_q15);
    PQ_WaitDone(POWERQUAD);

    TimerCount_Stop(tick_counter_val); /* 结束计时. */

    /* 打印计算结果. */
    for (uint32_t i = 0u; i < FFT_INPUT_NUM_512; i++) /* rfft只要一半的点数就能够表示足够的信息了. */
    {
        PRINTF("[%3d]: %d, %d\r\n", i, fft_output_q15[i*2], fft_output_q15[i*2+1]);
    }
    PRINTF("done with %d us.\r\n\r\n", tick_counter_val/96u); /* 打印计算时间. */
}

/* EOF. */

